package com.zmzncs.nat;

import com.zmzncs.nat.CommonConstants.ListenDest;
import com.zmzncs.nat.clientside.ClientControlThread;
import com.zmzncs.nat.clientside.config.AllSecretInteractiveClientConfig;
import com.zmzncs.nat.clientside.config.HttpRouteClientConfig;
import com.zmzncs.nat.clientside.config.InteractiveClientConfig;
import com.zmzncs.nat.clientside.config.SecretInteractiveClientConfig;
import com.zmzncs.nat.model.HttpRoute;
import lombok.extern.slf4j.Slf4j;

/**
 * 客户端，放在内网侧
 */
@Slf4j
public class ClientApp {

    public static void main(String[] args) {
//        simple();
        secret();
//        secretAll();
//        secretHttpRoute();
    }

    /**
     * 交互加密
     */
    public static void secret() {
        for (ListenDest model : CommonConstants.listenDestArray) {
            SecretInteractiveClientConfig config = new SecretInteractiveClientConfig();

            // 设置服务端IP和端口
            config.setClientServiceIp(CommonConstants.serviceIp);
            config.setClientServicePort(CommonConstants.servicePort);
            log.info("客户端-服务端IP和端口：（{}:{}）", CommonConstants.serviceIp, CommonConstants.servicePort);

            // 设置对外暴露的端口，该端口的启动在服务端，这里只是表明要跟服务端的那个监听服务对接
            config.setListenServerPort(model.listenPort);
            log.info("客户端-外网穿透端口：{}", model.listenPort);

            // 设置要暴露的目标IP和端口
            config.setDestIp(model.destIp);
            config.setDestPort(model.destPort);
            log.info("客户端-内网穿透IP和端口：（{}:{}）", model.destIp, model.destPort);

            // 设置签名key和交互密钥
            config.setBaseAesKey(CommonConstants.aesKey);
            config.setTokenKey(CommonConstants.tokenKey);
            log.info("客户端-签名key和交互密钥：（{}:{}）", CommonConstants.tokenKey, CommonConstants.aesKey);

            //  创建服务端连接
            new ClientControlThread(config).createControl();
        }
    }

    /**
     * http路由 默认使用交互加密、数据不加密的策略
     */
    public static void secretHttpRoute() {
        HttpRoute[] routes = new HttpRoute[] {
//                HttpRoute.of("localhost", "127.0.0.1", 8080),
     //           HttpRoute.of(true, "127.0.0.1", "192.168.0.211", 9020),
        };

        for (ListenDest model : CommonConstants.listenDestArray) {
            SecretInteractiveClientConfig baseConfig = new SecretInteractiveClientConfig();

            // 设置服务端IP和端口
            baseConfig.setClientServiceIp(CommonConstants.serviceIp);
            baseConfig.setClientServicePort(CommonConstants.servicePort);
            // 设置对外暴露的端口，该端口的启动在服务端，这里只是表明要跟服务端的那个监听服务对接
            baseConfig.setListenServerPort(model.listenPort);

            // 设置交互密钥和签名key
            baseConfig.setBaseAesKey(CommonConstants.aesKey);
            baseConfig.setTokenKey(CommonConstants.tokenKey);

            HttpRouteClientConfig config = new HttpRouteClientConfig(baseConfig);
            config.addRoute(routes);

            new ClientControlThread(config).createControl();
        }
    }

    /**
     * 交互、隧道都进行加密
     */
    public static void secretAll() {
        for (ListenDest model : CommonConstants.listenDestArray) {
            AllSecretInteractiveClientConfig config = new AllSecretInteractiveClientConfig();

            // 设置服务端IP和端口
            config.setClientServiceIp(CommonConstants.serviceIp);
            config.setClientServicePort(CommonConstants.servicePort);
            // 设置对外暴露的端口，该端口的启动在服务端，这里只是表明要跟服务端的那个监听服务对接
            config.setListenServerPort(model.listenPort);
            // 设置要暴露的目标IP和端口
            config.setDestIp(model.destIp);
            config.setDestPort(model.destPort);

            // 设置交互密钥和签名key
            config.setBaseAesKey(CommonConstants.aesKey);
            config.setTokenKey(CommonConstants.tokenKey);
            // 设置隧道交互密钥
            config.setBasePasswayKey(CommonConstants.aesKey);

            new ClientControlThread(config).createControl();
        }
    }

    /**
     * 无加密、无验证
     */
    public static void simple() {
        for (ListenDest model : CommonConstants.listenDestArray) {
            InteractiveClientConfig config = new InteractiveClientConfig();

            // 设置服务端IP和端口
            config.setClientServiceIp(CommonConstants.serviceIp);
            config.setClientServicePort(CommonConstants.servicePort);
            // 设置对外暴露的端口，该端口的启动在服务端，这里只是表明要跟服务端的那个监听服务对接
            config.setListenServerPort(model.listenPort);
            // 设置要暴露的目标IP和端口
            config.setDestIp(model.destIp);
            config.setDestPort(model.destPort);

            new ClientControlThread(config).createControl();
        }
    }

}
